﻿using System.Collections.Generic;

namespace Red.Scripts.Debugger.Defines.Enumerators
{
    public class Base<T, I> where I : class
    {
        #region Private Data

        private readonly IList<T> _data;
        private uint _position;

        #endregion Private Data

        #region C-Tor

        public Base( IList< T > data )
        {
            _data = data;
            _position = 0;
        }

        #endregion C-Tor

        #region Methods common to IEnum* interfaces

        public int Clone( out I ppEnum )
        {
            ppEnum = null;
            return Constants.E_NOTIMPL;
        }

        public int GetCount( out uint pcelt )
        {
            pcelt = (uint)_data.Count;
            return Constants.S_OK;
        }

        public int Next( uint celt, T[] rgelt, out uint celtFetched )
        {
            return Move( celt, rgelt, out celtFetched );
        }

        public int Reset()
        {
            lock ( this )
            {
                _position = 0;

                return Constants.S_OK;
            }
        }

        public int Skip( uint celt )
        {
            uint celtFetched;

            return Move( celt, null, out celtFetched );
        }

        private int Move( uint celt, T[] rgelt, out uint celtFetched )
        {
            lock ( this )
            {
                int hr = Constants.S_OK;
                celtFetched = (uint)_data.Count - _position;

                if ( celt > celtFetched )
                {
                    hr = Constants.S_FALSE;
                }
                else if ( celt < celtFetched )
                {
                    celtFetched = celt;
                }

                if ( rgelt != null )
                {
                    for ( int c = 0; c < celtFetched; c++ )
                    {
                        int index = (int)_position + c;
                        rgelt[ c ] = _data[ index ];
                    }
                }

                _position += celtFetched;

                return hr;
            }
        }

        #endregion Methods common to IEnum* interfaces
    }
}
